package com.hhsjdesign.dynamicui.core.widgetdata

import com.hhsjdesign.dynamicui.businessdata.BusinessDataParser
import com.hhsjdesign.dynamicui.businessdata.IViewable
import com.hhsjdesign.dynamicui.utils.WidgetSpecPropertyParser
import com.hhsjdesign.dynamicui.core.property.ViewBaseProperty
import com.hhsjdesign.dynamicui.core.property.WidgetItemProperty
import com.hhsjdesign.dynamicui.core.property.WidgetSpecProperty
import com.hhsjdesign.dynamicui.core.property.viewdata.ItemViewDataParser
import com.hhsjdesign.dynamicui.utils.ItemViewTypeConst
import com.hhsjdesign.dynamicui.utils.WidgetDataParser
import org.json.JSONArray
import org.json.JSONObject

/**
 * 视图的原始数据，然后需要转成 ViewTree 去管理和加载
 */
open class WidgetData {

    /**
     * 组件唯一id
     */
    var widgetId: String? = null

    /**
     * 组件链id
     */
    var linkedId: String? = null

    var name: String? = null

    //组件id链
    var widgetTreeId: String? = null

    /**
     * 父布局类型，用于设置widget，这个是设置进去的，后面注入的
     */
    var parentLayoutType: String? = null

    //视图类型，大的分类(布局组件，业务组件，视图组件)
    var category: String? = null

    //组件类型编码
    var type: String? = null

    //组件属性
    var specProperty: WidgetSpecProperty? = null

    //视图属性
    var viewProperty: ViewBaseProperty? = null

    //========以下只有业务组件有相关数据==================

    //业务类型
    var business: String? = null

    //数据来源，网络，还是带来的（0，随视图一起发来的，1，需要请求）
    var dataSource: Int = 0

    //业务参数（json字符串）
    var params: String? = null

    //业务数据数据
    var businessData: MutableList<IViewable<*>>? = null

    //业务视图属性 list
    var itemPropertyList: MutableList<WidgetItemProperty>? = null

    //子组件元素
    var childData: MutableList<WidgetData>? = null


    constructor(widgetId: String, type: String) {
        this.widgetId = widgetId
        this.type = type
    }

    constructor(jo: JSONObject) : this(jo, null)

    constructor(jo: JSONObject, linkedId: String?) {
        widgetId = jo.optString("widgetId")
        this.linkedId = if (linkedId == null || linkedId.isEmpty()) widgetId else "${linkedId}_${widgetId}"
        name = jo.optString("name")
        type = jo.optString("type")
        category = jo.optString("category")
        viewProperty = parseBaseProperty(jo.optJSONObject("viewProperty"))
        specProperty = parseSpecProperty(jo.optJSONObject("widgetProperty"))
        business = jo.optString("business")
        params = jo.optString("params")
        dataSource = jo.optInt("dataSource", SOURCE_TYPE_FIXED)
        businessData = parseBusinessData(jo.optJSONArray("businessData"))
        itemPropertyList = parseItemProperty(jo.optJSONArray("childProperty"))

        //布局组件才能有child
        if (type == WidgetTypeConst.LAYOUT_FRAME
            || type == WidgetTypeConst.LAYOUT_RELATIVE
            || type == WidgetTypeConst.LAYOUT_LINEAR_VERTICAL
            || type == WidgetTypeConst.LAYOUT_LINEAR_HORIZONTAL
        ) {
            //递归遍历
            childData = parseChild(jo.optJSONArray("childData"), type)
        }

    }

    private fun parseItemProperty(optJSONArray: JSONArray?): MutableList<WidgetItemProperty>? {
        optJSONArray ?: return null
        return ArrayList<WidgetItemProperty>().apply {
            for (i in 0 until optJSONArray.length()) {
                add(WidgetItemProperty().apply {
                    itemProperty = optJSONArray.optJSONObject(i)
                    itemProperty.let {
                        transformItemWidget(
                            type ?: "",
                            this,
                            it!!
                        )
                    }
                })
            }
        }
    }

    private fun parseChild(
        optJSONArray: JSONArray?,
        parentWidgetType: String?
    ): MutableList<WidgetData>? {
        optJSONArray ?: return null
        return ArrayList<WidgetData>().apply {
            for (i in 0 until optJSONArray.length()) {
                WidgetDataParser.parseWidget(optJSONArray.optJSONObject(i), parentWidgetType)?.let {
                    add(it)
                }
            }
        }
    }

    //解析基本属性
    open fun parseBaseProperty(jo: JSONObject?): ViewBaseProperty {
        return ViewBaseProperty.fromJSON(jo)
    }

    //解析特殊属性
    open fun parseSpecProperty(jo: JSONObject?): WidgetSpecProperty? {
        jo ?: return null
        return WidgetSpecPropertyParser.parse(type!!, jo)
    }

    //解析业务相关
    open fun parseBusinessData(ja: JSONArray?): MutableList<IViewable<*>>? {
        ja ?: return null
        return ArrayList<IViewable<*>>().apply {
            for (i in 0 until ja.length()) {
                var iViewableTransformer =
                    BusinessDataParser.createData(
                        business!!,
                        widgetId,
                        widgetTreeId,
                        ja.optJSONObject(i)!!
                    )
                if (iViewableTransformer is IViewable.IRedDotTree) {
                    iViewableTransformer.treeId(widgetId, widgetTreeId)
                }
                iViewableTransformer?.toViewable()?.let {
                    add(it)
                }
            }
        }
    }


    /**
     * 布局常量
     */
    companion object {

        //数据类型固定的
        const val SOURCE_TYPE_FIXED = 0

        //数据类型动态的
        const val SOURCE_TYPE_DYNAMIC = 1

        //组件总类只有3种
        //布局组件
        const val WIDGET_CATEGORY_LAYOUT = "layout"

        //通用业务组件
        const val WIDGET_CATEGORY_COMMON_BUSINESS = "common_business"

        //特定业务组件
        const val WIDGET_CATEGORY_FIXED_BUSINESS = "fixed_business"


        @JvmStatic
        fun transformItemWidget(
            widgetType: String,
            widgetItemProperty: WidgetItemProperty,
            itemPropertyJson: JSONObject
        ) {
            widgetItemProperty.itemWidgetType =
                itemPropertyJson.optString("itemWidgetType", ItemViewTypeConst.LEFT_BIG_RIGHT_2_SMALL)
            widgetItemProperty.itemWidgetType?.let {
                //已有类型解析
                ItemViewDataParser.parseItemViewDataByType(
                    itemPropertyJson
                )?.apply {
                    widgetItemProperty.itemPropertyModel = this@apply
                }
            }
            //如果没有已有类型，将操作的是普通类型解析
            if (widgetItemProperty.itemPropertyModel == null) {
                widgetItemProperty.itemPropertyModel = ItemViewDataParser.transform(
                    itemPropertyJson.optJSONObject("layout"),
                    itemPropertyJson,
                    widgetType,
                    0
                )
            }
        }
    }


    interface WidgetType {
        companion object {
            //布局只有3种
            const val LAYOUT_FRAME = "layout_frame"
            const val LAYOUT_LINEAR_HORIZONTAL = "layout_linear_h"
            const val LAYOUT_LINEAR_VERTICAL = "layout_linear_v"

            //用于处理父layoutparams
            const val LAYOUT_RELATIVE = "layout_relative"

            const val LAYOUT_IMAGE = "layout_image"
            const val LAYOUT_TEXT = "layout_text"
            const val LAYOUT_PLACEHOLDER = "layout_place_holder"

            //通用业务组件类型
            const val IMAGE = "image"
            const val TEXT = "text"
            const val PLACEHOLDER = "place_holder"

            //通用业务组件类型
            const val BANNER_GRID = "banner_grid"

            //通用业务组件类型
            const val BANNER_SINGLE = "banner_single"

            //通用业务组件类型
            const val GRID_VERTICAL = "grid_v"

            //通用业务组件类型
            const val GRID_HORIZONTAL = "grid_h"

            //通用业务组件类型
            const val LIST = "list"

            //通用业务组件类型
            const val FLIP = "flip"
        }
    }


    override fun hashCode(): Int {
        var result = 17
        result = 31 * result + if (widgetId == null) 0 else widgetId.hashCode()
        result = 31 * result + if (parentLayoutType == null) 0 else parentLayoutType.hashCode()
        return result
    }

    // TODO: 2021/12/23  组件比较
    override fun equals(other: Any?): Boolean {
        if (this == other) return true
        if (other is WidgetData) {
            return this.widgetId == other.widgetId &&
                    this.businessData == other.businessData
        }
        return super.equals(other)
    }

    fun businessDataList(): List<Any>? {
        if (businessData != null) {
            val result: MutableList<Any> = ArrayList()
            businessData!!.forEach {
                result.add(it.businessData!!)
            }
            return result
        }
        return null;
    }

}